import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class ScannerGenerator {

	ArrayList<Rule> rules;

	public ScannerGenerator() {

		rules = new ArrayList<Rule>();

	}

	public void addRule(String s) {
		if (getRule(s) == null)
			rules.add(new Rule(s, this));

	}

	public Rule getRule(String s) {
		if (s.contains(" "))
			s = s.substring(0, s.indexOf(' '));
		for (int i = 0; i < rules.size(); i++)
			if (rules.get(i).getName().equals(s))
				return rules.get(i);

		return null;
	}

	public NFA combineTokens() {

		return null;
	}

	public static void main(String args[]) throws IOException {

		@SuppressWarnings("unused")
		String s = "";

		ScannerGenerator grammarScanner = new ScannerGenerator();
		ScannerGenerator scriptScanner = new ScannerGenerator();

		// Specification of how to read the grammar
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(args[0]));
			String line = br.readLine();

			while (line != null) {
				if (line.length() > 1) {
					grammarScanner.addRule(line);
					// sg.rules.get(sg.rules.size()-1).getNFA().cloneNFA(true);
				}
				line = br.readLine();
			}
		} finally {
			br.close();
		}

		// Specification of how to read the script

		try {
			br = new BufferedReader(new FileReader(args[1]));
			String line = br.readLine();

			while (line != null) {
				if (line.length() > 1) {
					scriptScanner.addRule(line); // CHANGE BACK LATER!!!!
					// scriptScanner.rules.get(scriptScanner.rules.size()-1).getNFA().cloneNFA(true);
				}
				line = br.readLine();
			}
		} finally {
			br.close();
		}

		DFA d = DFA.produceDFA(grammarScanner.rules);

		DFA d2 = DFA.produceDFA(scriptScanner.rules);
		// d.printTable();
		// d.writeTableToFile(args[2]);

		// read in the script and assign values to each thing
		FileWriter fstream;
		BufferedWriter out = null;

		Grammar g = new Grammar();

		String totalScript = "";

		int lineNumber = 1;

		// Read grammar file using scanner for Grammar
		try {
			br = new BufferedReader(new FileReader(args[2]));
			String line = br.readLine();

			while (line != null) {
				s += line;
				totalScript = grammarScanner.project1Print(line, d, false);
				if (!line.isEmpty())
					g.addGrammarRule(new GrammarRule(totalScript, g, "", lineNumber));

				// System.out.println(grammarScanner.project1Print(line,d,false));
				line = br.readLine();
				lineNumber++;
			}

		} catch (FileNotFoundException e) {
			System.out.println("Didn't work");
		} finally {
			br.close();
		}

		// System.out.print(g.toString());

		g.calculateRules();

		LLParser lp = new LLParser(g);
		lineNumber = 1;

		// Read script file using scanner for script
		try {
			br = new BufferedReader(new FileReader(args[3]));

			// br = new BufferedReader(new FileReader("9/scriptComp.txt")); //
			// TEMPORARY!
			// CHANGE
			// LATER

			String line = br.readLine();

			while (line != null) {

				totalScript = scriptScanner.project1Print(line, d2, false);

				// totalScript += line + "\n"; // TEMPORARY, CHANGE LATER

				
				
				lp.addInput(totalScript, lineNumber);

				line = br.readLine();

				lineNumber++;
			}

		} catch (Exception e) {

		} finally {
			br.close();

		}

		Script script = new Script(totalScript);

		while(lp.step(true));

		// System.out.print(totalScript);

		// System.out.print(g.toString());

	}

	public String project1Print(String s, DFA d, boolean printOut) {

		String curr = s;
		String k = "", m = "";

		m = checkMatch(curr, d);
		
		k += m;

		if (printOut)
			System.out.print(m);
		curr = "";

		return k;
	}

	public String checkMatch(String s, DFA d) {

		String poss2 = null;

		if (s.isEmpty()) {
			return "";
		}

		String poss = null;

		String curr = "";

		int max = 0;

		String buff = "";

		boolean fail=false;
		
		for (int k = 1; k <= s.length(); k++) {
			poss = d.match(s.substring(0, k), this);
			if (poss.length() != 0) {
				curr = poss + "";
				max = k;
			}
		}
		if (max == 0) {
			max = 1;
			fail=true;
		}
		if(!fail)
			return curr + " " + s.substring(0, max) + " \n"
				+ checkMatch(s.substring(max, s.length()), d);

		return checkMatch(s.substring(max, s.length()),d);
	}
}